<template>
  <van-field
    v-model="fieldLabel"
    :disabled="disabled"
    :is-link="!readonly"
    :label="label"
    :label-align="_labelAlign"
    :placeholder="readonly ? '' : `请选择${label}`"
    :required="required"
    :rules="rules"
    autocomplete="off"
    clear-trigger="always"
    clearable
    readonly
    @clear="emit('update:modelValue', null)"
    @click="!readonly && !disabled && (showPicker = true)"
  />
  <van-popup v-model:show="showPicker" :lazy-render="false" position="bottom" round teleport="body" @open="onOpen">
    <van-cell-group v-if="search && !tree" inset>
      <div style="display: flex">
        <van-search
          v-model="searchValue"
          :clearable="false"
          :placeholder="`请输入${label}名称`"
          style="margin-right: 10vw"
        />
        <van-icon
          color="#1989fa"
          name="close"
          style="margin-top: auto; margin-bottom: auto"
          @click="showPicker = false"
        />
      </div>
      <div style="height: 80vh; overflow: auto">
        <van-cell
          v-for="item in selectOptions"
          :key="item[props.columnsFieldNames.value]"
          :title="item[props.columnsFieldNames.text]"
          @click="onClickItem(item)"
        />
        <van-cell>
          <van-button
            v-if="isEmpty(selectOptions) && addAble"
            block
            size="small"
            type="primary"
            @click="handleAddButton"
          >
            {{ '添加 ' + label }}
          </van-button>
          <p v-else class="tip">仅展示前 {{ pageSize }} 条数据</p>
        </van-cell>
      </div>
    </van-cell-group>
    <van-picker
      v-else-if="!tree"
      v-model="pickValue"
      :columns="selectOptions"
      :columns-field-names="columnsFieldNames"
      style="height: 60vh; overflow: auto"
      @cancel="showPicker = false"
      @confirm="onConfirm"
    />
    <template v-else>
      <van-tree-select
        v-model:active-id="treePickValue"
        v-model:main-active-index="mainActiveId"
        style="height: 60vh; overflow: auto"
        :items="selectOptions"
      />
      <div class="van-hairline--top van-dialog__footer">
        <button
          class="van-button van-button--default van-button--large van-dialog__cancel"
          type="button"
          @click="showPicker = false"
        >
          <div class="van-button__content">
            <span class="van-button__text">取消</span>
          </div>
        </button>
        <button
          class="van-button van-button--default van-button--large van-dialog__confirm van-hairline--left"
          type="button"
          @click="onConfirm"
        >
          <div class="van-button__content">
            <span class="van-button__text">确认</span>
          </div>
        </button>
      </div>
    </template>
  </van-popup>
</template>

<script lang="ts" setup>
import { FieldTextAlign } from 'vant'
import { getAllNodes, isEmpty, isNotEmpty } from '../../utils/common'
import _ from 'lodash'
import { QUERY_INTERVAL } from '@/framework/constant'
import { onBeforeMount, Ref } from 'vue'
import { useDictStore, useTreeStore } from '../../store/common'
import router from '../../router'

const props = withDefaults(
  defineProps<{
    modelValue: string | null
    label: string
    dict?: string
    columns?: any
    rules?: Array<any>
    required?: boolean
    labelAlign?: FieldTextAlign
    search?: boolean
    pageSize?: number
    columnsFieldNames?: any
    addAble?: any
    readonly?: boolean
    modelLabel?: string
    wrapLength?: number
    to?: string
    disabled?: boolean
    tree?: boolean
  }>(),
  {
    rules: undefined,
    dict: undefined,
    columns: [],
    labelAlign: 'left',
    search: false,
    pageSize: 30,
    columnsFieldNames: { text: 'label', value: 'value', children: 'children' },
    addAble: true,
    readonly: false,
    modelLabel: '',
    wrapLength: 15,
    to: '',
    disabled: false,
    tree: false
  }
)
const emit = defineEmits<{
  (e: 'update:modelValue', value: string | null): void
  (e: 'update:modelLabel', value: string): void
  (e: 'getSelectOptions', value: string, pageSize: number): void
}>()
const dictStore = useDictStore()
const treeStore = useTreeStore()
const showPicker: Ref<boolean> = ref(false)
const {
  columns,
  label,
  dict,
  modelValue,
  columnsFieldNames,
  rules,
  required,
  labelAlign,
  search,
  pageSize,
  addAble,
  readonly,
  wrapLength,
  to,
  disabled,
  tree
} = toRefs(props)
const pickValue = ref([modelValue.value])
const treePickValue = ref(modelValue.value)
const mainActiveId = ref()
const fieldLabel = ref('')
const searchValue = ref('')
const selectOptions = ref(columns.value)
const _labelAlign = ref(labelAlign.value)
watch(
  () => columns.value,
  () => {
    selectOptions.value = columns.value
  },
  {
    immediate: true
  }
)

watch(
  [() => modelValue.value, () => selectOptions.value],
  () => {
    isEmpty(modelValue.value) && (fieldLabel.value = '')
    if (tree.value) {
      getAllNodes(selectOptions.value, (option: any) => {
        if (option[props.columnsFieldNames.value] === modelValue.value) {
          fieldLabel.value = option[props.columnsFieldNames.text]
          return
        }
      })
    } else {
      selectOptions.value.forEach((option: any) => {
        if (option[props.columnsFieldNames.value] === modelValue.value) {
          fieldLabel.value = option[props.columnsFieldNames.text]
          return
        }
      })
    }
  },
  {
    immediate: true
  }
)

watch(
  () => searchValue.value,
  _.debounce(() => {
    if (dict.value) {
      if (isEmpty(searchValue.value)) {
        dictStore.getDict(dict.value, selectOptions)
      } else {
        selectOptions.value = selectOptions.value.filter(
          (option: any) => option[props.columnsFieldNames.text].indexOf(searchValue.value) !== -1
        )
      }
    }
    emit('getSelectOptions', searchValue.value, pageSize.value)
  }, QUERY_INTERVAL)
)

watch(
  () => fieldLabel.value,
  () => {
    emit('update:modelLabel', fieldLabel.value)
    if (fieldLabel.value.length > wrapLength.value) {
      _labelAlign.value = 'top'
    }
  }
)

watch(
  () => labelAlign.value,
  () => (_labelAlign.value = labelAlign.value)
)

const onConfirm = ({ selectedOptions }: any) => {
  showPicker.value = false
  if (selectedOptions[0]) {
    fieldLabel.value = selectedOptions[0][props.columnsFieldNames.text]
    emit('update:modelValue', selectedOptions[0][props.columnsFieldNames.value])
  }
}
const onClickItem = (item: any) => {
  emit('update:modelValue', item[props.columnsFieldNames.value])
  fieldLabel.value = item[props.columnsFieldNames.text]
  showPicker.value = false
}

const onOpen = () => {
  emit('getSelectOptions', searchValue.value, pageSize.value)
}

const handleAddButton = () => {
  if (isNotEmpty(to.value)) {
    showPicker.value = false
    router.push(to.value)
  }
}
onBeforeMount(() => {
  if (dict.value) {
    if (tree.value) {
      treeStore.getTree(dict.value, selectOptions)
    } else {
      dictStore.getDict(dict.value, selectOptions)
    }
  }
})
</script>
